﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

	<head>
		<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
		<title>Data Filters</title>
		<link type="text/css" rel="stylesheet" href="bootstrap.min.css" />
		<style type="text/css">
.auto-style1 {
	text-decoration: underline;
}
		</style>
	</head>

	<body>

		<div class="document-contents">

			<h3 id="DocIntro">Introduction</h3>
			<p>It's common to use the <a href="/Pages/Documents/Entities#DocSoftDelete">
					<strong>soft-delete</strong>
				</a> pattern which is used to not delete an entity 
from database but only mark it as 'deleted'. So, if an entity is soft-deleted, 
it should not be accidently retrieved into the application. To provide that, we 
would add a SQL <strong>where</strong> condition like 'IsDeleted = false' in 
every query we select entities. This is a tedious but more importantly a 
forgettable task. So, there should be an automatic way of it.</p>
			<p>ASP.NET Boilerplate provides <strong>data filters </strong>those can be used 
to automatically filter queries based on some rules. There are some pre-defined 
filters, but also you can create your own filters.</p>

			<h3 id="DocPredefinedFilters">Pre-Defined Filters</h3>

			<h4 id="DocSoftDelete">ISoftDelete</h4>
			<p>Soft-delete filter is used to automatically filter (extract from results) 
deleted entities while querying database. If an
				<a href="/Pages/Documents/Entities">entity</a> should be soft-deleted, it must 
implement <strong>ISoftDelete</strong> interface which defines only <strong>IsDeleted</strong> 
property. Example:</p>
			<pre lang="cs">public class Person : Entity, <strong>ISoftDelete</strong>
{
    public virtual string Name { get; set; }

    <strong>public virtual bool IsDeleted { get; set; }</strong>
}</pre>
			<p>A <strong>Person </strong>entity is not actually deleted from database, 
instead <strong>IsDeleted </strong>property is set to true when need to delete 
it. This is done automatically by ASP.NET Boilerplate when you use <strong>
					<a href="/Pages/Documents/Repositories#DocDeleteEntity">IRepository.Delete</a>
				</strong> 
method (you can manually set IsDeleted to true, but Delete method is more 
natural and preffered way).</p>
			<p>After implementing ISoftDelete, when you get list of People from database, 
deleted people are not retrieved. Here, an example class that uses a person 
repository to get all people:</p>
			<pre lang="cs">public class MyService
{
    private readonly IRepository&lt;Person&gt; _personRepository;

    public MyService(IRepository&lt;Person&gt; personRepository)
    {
        _personRepository = personRepository;
    }

    public List&lt;Person&gt; GetPeople()
    {
        return _personRepository.GetAllList();
    }
}</pre>
			<p>GetPeople method only gets Person entities which has IsDeleted = false (not 
deleted). All repository methods and also navigation properties properly works. 
We could add some other Where conditions, joins.. etc. It will automatically add 
IsDeleted = false condition properly to the generated SQL query.</p>

			<div class="bs-callout bs-callout-warning">
				<h4>When Enabled?</h4>
				<p>ISoftDelete filter is always enabled unless you explicitly disable it.</p>
			</div>

			<p>
				<span class="auto-style1">A side note</span>: If you implement
				<a href="/Pages/Documents/Entities#DocSoftDelete">IDeletionAudited</a> (which 
extends ISoftDelete) then deletion time and deleter user id are also 
automatically set by ASP.NET Boilerplate.</p>

			<h4 id="DocMustHaveTenant">IMustHaveTenant</h4>
			<p>If you are building multi-tenant applications and store all tenant data in 
single database, you definitely do not want a tenant accidently see other's 
data. You can implement <strong>IMustHaveTenant</strong> in that case. Example:</p>
			<pre lang="cs">public class Product : Entity, <strong>IMustHaveTenant</strong>
{
    <strong>public int TenantId { get; set; }</strong>

    public string Name { get; set; }
}</pre>
			<p>
				<strong>IMustHaveTenant</strong> defines <strong>TenantId </strong>to 
distinguish different tenant entities. ASP.NET Boilerplate uses
				<a href="/Pages/Documents/Abp-Session">IAbpSession</a> to get current TenantId 
				by default 
and automatically filter query for the current tenant.</p>

			<div class="bs-callout bs-callout-warning">
				<h4>When Enabled?</h4>
				<p>IMustHaveTenant is enabled by default.</p>
				<p>If current user is not logged in to the system or current user is a <strong>host</strong> user (Host user is an upper level user that can 
	manage tenants and tenant data), ASP.NET Boilerplate automatically <strong>
	disables</strong> IMustHaveTenant filter. Thus, all data of all tenant's can be 
	retrieved to the application. Notice that this is not about security, you should 
	always <a href="/Pages/Documents/Authorization">authorize</a> sensitive data.</p>
			</div>

			<h4 id="DocMayHaveTenant">IMayHaveTenant</h4>
			<p>If an entity class shared by tenants and the host (that means an entity 
object may 
be owned by a tenant or the host), you can use IMayHaveTenant filter. <strong>
IMayHaveTenant</strong> interface defines <strong>TenantId</strong> but it's <strong>
nullable</strong>.</p>
			<pre lang="cs">public class Role : Entity, <strong>IMayHaveTenant</strong>
{
    <strong>public int? TenantId { get; set; }</strong>

    public string RoleName { get; set; }
}</pre>
			<p>A <strong>null</strong> value means this is a <strong>host</strong> entity, a <strong>non-null</strong> value means this entity 
owned by a <strong>tenant</strong> which's Id is the TenantId. ASP.NET Boilerplate uses
				<a href="/Pages/Documents/Abp-Session">IAbpSession</a> to get current TenantId 
			by default. 
IMayHaveTenant filter is not common as much as 
IMustHaveTenant. But you may need it for <strong>common entitiy types</strong> used by host and tenants.</p>

			<div class="bs-callout bs-callout-warning">
				<h4>When Enabled?</h4>
				<p>IMayHaveTenant is always enabled unless you explicitly disable it.</p>
			</div>

			<h3 id="DocDisableFilters">Disable Filters</h3>
			<p>You can disable a filter per <a href="/Pages/Documents/Unit-Of-Work">unit of 
work</a> by calling <strong>DisableFilter</strong> method as shown below:</p>
			<pre lang="cs">var people1 = _personRepository.GetAllList();

using (<strong>_unitOfWorkManager.Current.DisableFilter(AbpDataFilters.SoftDelete)</strong>)
{
    var people2 = _personRepository.GetAllList();                
}

var people3 = _personRepository.GetAllList();</pre>
			<p>DisableFilter method gets one or more filter names as strings. 
AbpDataFilters.SoftDelete is a constant string that contains name of the 
standard soft 
delete filter of ASP.NET Boilerplate.</p>
			<p>
				<strong>people2</strong> will also include deleted people while people1 and people3 will be only 
non-deleted people. With <strong>using </strong>statement, you can disable a filter in a
				<strong>scope</strong>. 
If you don't use using stamement, filter will be disabled until end of the&nbsp;current unit of work or you enable it again 
explicitly.</p>
			<p>You can inject <strong>IUnitOfWorkManager </strong>and use as in the example. Also, you can 
use <strong>CurrentUnitOfWork </strong>property as a shortcut if you class 
			inherits some special base classes (like ApplicationService, 
			AbpController, AbpApiController...).</p>

			<div class="bs-callout bs-callout-warning">
				<h4>About using Statement</h4>
				<p>If a filter is enabled when you call 
	the DisableFilter method with a using statement, the filter is disabled, then 
	automatically re-enabled after using statement.
	But if the filter was already 
	disabled before the using statement, DisableFilter actually does nothing and 
	the filter remains disabled even after 
	the using statement.</p>
			</div>

			<div class="bs-callout bs-callout-warning">
				<h4>About Multi Tenancy</h4>
				<p>You can disable tenancy filters to query all tenant data. But 
				remember that, this works only for single database approach. If 
				you have seperated databases for each tenants, disabling filter 
				does not help to query all data of all tenants, since they are 
				in different databases, can be even in different servers. See
				<a href="Multi-Tenancy.html">multi tenancy document</a> for more 
				information.</p>
			</div>
<h4>Disable Filters Globally</h4>
			<p>If you need, you can disable pre-defined filters globally. For 
			example, to disable soft delete filter globally, add this code to 
			PreInitialize method of your module:</p>
			<pre lang="cs">Configuration.UnitOfWork.OverrideFilter(AbpDataFilters.SoftDelete, false);</pre>
			<h3 id="DocEnableFilters">Enable Filters</h3>
			<p>You can enable a filter in a unit of work using <strong>EnableFilter </strong>
method, as similar to (and opposite of) DisableFilter. EnableFilter also returns disposable to 
			be used in a <strong>using</strong> statement to automatically re-disable the filter 
			if needed.</p>

			<h3 id="DocSetFilterParams">Setting Filter Parameters</h3>
			<p>A filter can be <strong>parametric</strong>. IMustHaveTenant filter is an 
example of these types of filters since current tenant's Id is determined on 
runtime. For such filters, we can change filter value if needed. Example:</p>
			<pre lang="cs">CurrentUnitOfWork.SetFilterParameter("PersonFilter", "personId", 42);</pre>
			<p>Another example: To set the tenantId value for the IMayHaveTenant filter:</p>
			<pre lang="cs">CurrentUnitOfWork.SetFilterParameter(AbpDataFilters.MayHaveTenant, AbpDataFilters.Parameters.TenantId, 42);</pre>

			<p>SetFilterParameter method also returns an IDisposable. So, we can use it in a
				<strong>using</strong> statement to automatically <strong>restore the old value</strong> 
after using statement.</p>
			<h4>SetTenantId Method</h4>

			<p>While you can use SetFilterParameter method to change filter 
			value for MayHaveTenant and MustHaveTenant filters, there is a 
			better way to change tenant filter: <strong>SetTenantId()</strong>. 
			SetTenantId changes parameter value for both filters, and also 
			works for single database and database per tenant approaches. 
			So, it's <strong>always suggested to use SetTenantId</strong> to change tenancy 
			filter parameter values. See
			<a href="Multi-Tenancy.html">multi tenancy document</a> for more 
			information.</p>

			<h3 id="DocDefineCustomFilters">ORM Integrations</h3>
			<p>Data filtering for pre-defined filters works for
			<a href="NHibernate-Integration.html">NHibernate</a>,
			<a href="EntityFramework-Integration.html">Entity Framework</a> 6.x 
			and <a href="Entity-Framework-Core.html">Entity Framework Core</a>. 
			Currently, you can only define custom filters for Entity Framework 
			6.x.</p>
			<h4>Entity Framework</h4>
			<p>For <a href="EntityFramework-Integration.html">Entity Framework 
			integration</a>, automatic data filtering is implemented using<strong>
					<a href="https://github.com/jcachat/EntityFramework.DynamicFilters" target="_blank">EntityFramework.DynamicFilters</a></strong> 
			library. </p>
			<p>To create a custom filter for Entity Framework and integrate to ASP.NET Boilerplate, first we 
should define an interface that will be implemented by entities which use this 
filter. Assume that we want to automatically filter entities by PersonId. 
Example interface:</p>
			<pre lang="cs">public interface IHasPerson
{
    <strong>int PersonId { get; set; }
</strong>}</pre>
			<p>Then we can implement this interface for needed entities. Example entity:</p>
			<pre lang="cs">public class Phone : Entity, <strong>IHasPerson</strong>
{
    [ForeignKey("PersonId")]
    public virtual Person Person { get; set; }
    public virtual int PersonId { get; set; }

    public virtual string Number { get; set; }
}</pre>
			<p>We use it's 
rules to define the filter. In our <strong>DbContext </strong>class, we override 
				<strong>OnModelCreating </strong>and define filter as shown below:</p>

			<pre lang="cs">protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    <strong>modelBuilder.Filter("PersonFilter", (IHasPerson entity, int personId) =&gt; entity.PersonId == personId, 0);</strong>
}</pre>
			<p>"PersonFilter" is the unique name of the filter here. Second parameter defines 
filter interface and personId filter parameter (not needed if filter is not 
parametric), last parameter is the default value of the personId.</p>
			<p>As the last thing, we must register this filter to ASP.NET Boilerplate's 
unit of work system in PreInitialize method of our 
				<a href="/Pages/Documents/Module-System">module</a>:</p>
			<pre lang="cs"><strong>Configuration.UnitOfWork.RegisterFilter("PersonFilter", false);</strong></pre>
			<p>First parameter is same unique name we defined before. Second parameter 
indicates whether this filter is enabled or disabled by default. After declaring such a parametric filter, we 
can use it by supplying it's value on 
runtime.</p>
			<pre lang="cs">using (<strong>CurrentUnitOfWork.EnableFilter("PersonFilter")</strong>)
{
    using(<strong>CurrentUnitOfWork.SetFilterParameter("PersonFilter", "personId", 42)</strong>)
    {
        var phones = _phoneRepository.GetAllList();
        //...
    }
}</pre>
			<p>We could get the personId from some source instead of statically coded. The example above was for parametric filters. A filter can have zero or more 
parameters. If it has no parameter, it's not needed to set the filter parameter value. 
Also, if it's enabled by default, no need to enable it manually (surely, we can 
disable it).</p>

			<div class="bs-callout bs-callout-warning">
				<h4>Documentation for EntityFramework.DynamicFilters</h4>
				<p>For more information on dynamic data filters, see documentation on it's github page: 
					<a href="https://github.com/jcachat/EntityFramework.DynamicFilters">https://github.com/jcachat/EntityFramework.DynamicFilters</a>
				</p>
			</div>

			<p>We can create custom filters for security, active/passive entities and so on.</p>

			<h4 id="DicOtherORMs">Other ORMs</h4>
			<p>For <a href="Entity-Framework-Core.html">Entity Framework Core</a> 
			and NHibernate, data filtering is implemented in the
			<a href="Repositories.html">repository</a> level. That means it only 
			filters when you query over repositories. If you directly use 
			DbContext (for EF Core) or query via custom SQL, you should handle 
			filtering yourself.</p>

		</div>

	</body>

</html>
